package com.enation.app.javashop.core.goods.service.impl;

import com.enation.app.javashop.core.base.CachePrefix;
import com.enation.app.javashop.core.goods.GoodsErrorCode;
import com.enation.app.javashop.core.goods.model.dos.GoodsDO;
import com.enation.app.javashop.core.goods.model.dos.GoodsGalleryDO;
import com.enation.app.javashop.core.goods.model.dos.GoodsSkuDO;
import com.enation.app.javashop.core.goods.model.vo.GoodsSkuVO;
import com.enation.app.javashop.core.goods.model.vo.SpecValueVO;
import com.enation.app.javashop.core.goods.service.GoodsGalleryManager;
import com.enation.app.javashop.core.goods.service.GoodsSkuManager;
import com.enation.app.javashop.framework.cache.Cache;
import com.enation.app.javashop.framework.context.UserContext;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.database.Page;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.security.model.Seller;
import com.enation.app.javashop.framework.util.JsonUtil;
import com.enation.app.javashop.framework.util.SqlUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商品sku业务类
 * 
 * @author fk
 * @version v2.0
 * @since v7.0.0 2018-03-21 11:48:40
 */
@Service
public class GoodsSkuManagerImpl implements GoodsSkuManager {

	@Autowired
	@Qualifier("goodsDaoSupport")
	private DaoSupport daoSupport;

	@Autowired
	private GoodsGalleryManager goodsGalleryManager;
	
	@Autowired
	private Cache cache;

	@Override
	public Page list(int page, int pageSize) {

		String sql = "select * from es_goods_sku  ";
		Page webPage = this.daoSupport.queryForPage(sql, page, pageSize, GoodsSkuDO.class);

		return webPage;
	}

	@Override
	@Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public GoodsSkuDO add(GoodsSkuDO goodsSku) {
		this.daoSupport.insert(goodsSku);

		return goodsSku;
	}

	@Override
	@Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public GoodsSkuDO edit(GoodsSkuDO goodsSku, Integer id) {
		this.daoSupport.update(goodsSku, id);
		return goodsSku;
	}

	@Override
	@Transactional(value = "goodsTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public void delete(Integer id) {
		this.daoSupport.delete(GoodsSkuDO.class, id);
	}

	@Override
	public GoodsSkuDO getModel(Integer id) {
		return this.daoSupport.queryForObject(GoodsSkuDO.class, id);
	}

	@Override
	public void add(List<GoodsSkuVO> skuList, GoodsDO goods) {
		// 如果有规格
		if (skuList != null && skuList.size() > 0) {
			// 添加商品sku
			this.addGoodsSku(skuList, goods);
		} else {
			// 添加没有规格的sku信息
			this.addNoSku(goods);
		}
	}

	/**
	 * 增加sku集合
	 * 
	 * @param skuList
	 * @param goods
	 */
	private void addGoodsSku(List<GoodsSkuVO> skuList, GoodsDO goods) {

		for (GoodsSkuVO skuVO : skuList) {
			GoodsSkuDO sku = new GoodsSkuDO();
			BeanUtils.copyProperties(skuVO,sku);

			sku.setEnableQuantity(sku.getQuantity());
			sku.setGoodsName(goods.getGoodsName());
			sku.setCategoryId(goods.getCategoryId());
			// 得到规格值的json
			String specJson = getSpecListJson(skuVO.getSpecList());
			sku.setSpecs(specJson);
			sku.setGoodsId(goods.getGoodsId());
			sku.setSellerId(goods.getSellerId());
			sku.setSellerName(goods.getSellerName());
			sku.setThumbnail(goods.getThumbnail());

			this.daoSupport.insert(sku);
			Integer skuId = this.daoSupport.getLastId("es_goods_sku");
			skuVO.setSkuId(skuId);
		}
	}

	/**
	 * sku中的spec字段的操作，返回json
	 * 
	 * @param specList
	 *            规格值集合
	 * @return 规格值json
	 */
	private String getSpecListJson(List<SpecValueVO> specList) {
		String spenJson = null;
		for (SpecValueVO specvalue : specList) {
			if (specvalue.getSpecType() == null) {
				specvalue.setSpecType(0);
			}
			if (specvalue.getSpecType() == 1) {
				GoodsGalleryDO goodsGallery = goodsGalleryManager.getGoodsGallery(specvalue.getSpecImage());
				specvalue.setBig(goodsGallery.getBig());
				specvalue.setSmall(goodsGallery.getSmall());
				specvalue.setThumbnail(goodsGallery.getThumbnail());
				specvalue.setTiny(goodsGallery.getTiny());
				// 规格只有第一个规格有图片，所以找到有图片的规格后就可跳出循环
				break;
			}
		}
		spenJson = JsonUtil.objectToJson(specList);
		return spenJson;
	}

	/**
	 * 添加没有规格的sku信息
	 * 
	 * @param goods
	 *            商品信息
	 * @return
	 */
	private GoodsSkuDO addNoSku(GoodsDO goods) {

		GoodsSkuDO goodsSku = new GoodsSkuDO();
		BeanUtils.copyProperties(goods,goodsSku);
		goodsSku.setEnableQuantity(goodsSku.getQuantity());

		this.daoSupport.insert("es_goods_sku", goodsSku);
		goodsSku.setSkuId(this.daoSupport.getLastId("es_goods_sku"));
		return goodsSku;
	}

	@Override
	public void edit(List<GoodsSkuVO> skuList, GoodsDO goods, Integer hasChanged) {
		// 如果编辑的时候sku数据有变化(包括规格项组合变了，有规格改成无规格，无规格改成有规格) hasChanged=1 规格有改变
		Integer goodsId = goods.getGoodsId();
		// 清除缓存及库中的sku
		this.clean(goodsId);
		//有变化
		if (hasChanged == 1) {
			this.daoSupport.execute("delete from es_goods_sku where goods_id=? ", goodsId);
			// 如果有规格
			this.add(skuList, goods);
		} else {
			// 如果没有改变规格组合
			if (skuList != null && skuList.size() > 0) {
				// 先把与原sku组合缺少的删掉
				this.deleteNoUseSku(skuList, goods);

				// 修改sku
				this.updateGoodsSku(skuList, goods);

			} else {
				// 修改没有规格的sku信息
				GoodsSkuDO goodsSku = new GoodsSkuDO();
				BeanUtils.copyProperties(goods,goodsSku);
				Map map = new HashMap(16);
				map.put("goods_id",goods.getGoodsId());

				this.daoSupport.update("es_goods_sku",goodsSku, map);
			}
		}

	}
	
	/**
	 * 清除商品规格信息和sku信息 及缓存
	 * @param goodsId  商品id
	 */
	private void clean(Integer goodsId) {
		String sql = "select sku_id from es_goods_sku where goods_id =?";
		List<Map> list = daoSupport.queryForList(sql,goodsId);
		for (Map skuMap : list) {
			cache.remove(CachePrefix.SKU.getPrefix() + skuMap.get("sku_id"));
		}
	}
	
	/**
	 * 删除没有传过来的sku(例：原商品sku组合1，2，3，现传过来1，3 就要把2删掉)
	 * 
	 * @param skuList
	 *            新的sku组合
	 * @param goods
	 *            商品
	 */
	private void deleteNoUseSku(List<GoodsSkuVO> skuList, GoodsDO goods) {
		List<Object> term = new ArrayList<>();
		String[] temp = new String[skuList.size()];
		if (skuList.size() > 0) {
			for (int i = 0; i < skuList.size(); i++) {
				if (skuList.get(i).getSkuId() == null) {
					throw new ServiceException(GoodsErrorCode.E301.name(), "sku信息错误");
				}
				term.add(skuList.get(i).getSkuId());
				temp[i] = "?";
			}
		}
		String str = StringUtil.arrayToString(temp, ",");
		term.add(goods.getGoodsId());
		/** 删除不在此商品sku组合中sku */
		this.daoSupport.execute("delete from es_goods_sku where sku_id not in(" + str + ") and goods_id = ?",
				term.toArray());

	}
	/**
	 * 不更改sku组合时 修改sku信息
	 * 
	 * @param skuList
	 *            sku集合
	 * @param goods
	 *            商品信息
	 */
	private void updateGoodsSku(List<GoodsSkuVO> skuList, GoodsDO goods) {
		List<GoodsSkuVO> newSkuList = new ArrayList<>();
		for (GoodsSkuVO sku : skuList) {
			// 没有被用户移除的sku组合要修改
			if (sku.getSkuId()!=0) {
				// 得到规格值的json
				String specJson = getSpecListJson(sku.getSpecList());
				this.daoSupport.execute(
						"update es_goods_sku set category_id=?,goods_name=?,sn=?,price=?,cost=?,weight=?,thumbnail=? ,specs=? where sku_id=?",
						goods.getCategoryId(), goods.getGoodsName(), sku.getSn(), sku.getPrice(), sku.getCost(),
						sku.getWeight(), goods.getThumbnail(), specJson, sku.getSkuId());

				// 先删除商品规格表
				this.daoSupport.execute("delete from es_goods_spec where sku_id=?", sku.getSkuId());
				break;
			}
			// 新加的sku组合要入库 (skuid是0)
			if (sku.getSkuId()==0) {
				newSkuList.add(sku);
				break;
			}
		}
		// 如果有新的规格值
		if (newSkuList.size() > 0) {
			this.addGoodsSku(newSkuList, goods);
		}
	}

	@Override
	public void delete(Integer[] goodsIds) {
		List<Object> term = new ArrayList<>();
		String[] goods = new String[goodsIds.length];
		for (int i = 0; i < goodsIds.length; i++) {
			goods[i] = "?";
			term.add(goodsIds[i]);
		}
		String idStr = StringUtil.arrayToString(goods, ",");
		// 删除这个商品的sku缓存(必须要在删除库中sku前先删缓存),首先查出商品对应的sku_id
		String sql = "select sku_id from es_goods_sku where goods_id in (" + idStr + ")";
		List<Map> skuIds = this.daoSupport.queryForList(sql, term.toArray());
		for (Map map : skuIds) {
			cache.remove(CachePrefix.SKU.getPrefix() + map.get("sku_id"));
		}
		sql = "delete from es_goods_sku where goods_id in (" + idStr + ")";
		this.daoSupport.execute(sql, term.toArray());
	}

	@Override
	public List<GoodsSkuVO> listByGoodsId(Integer goodsId) {
		String sql = "select * from es_goods_sku where goods_id =?";
		List<GoodsSkuDO> list = daoSupport.queryForList(sql, GoodsSkuDO.class, goodsId);
		List<GoodsSkuVO> result = new ArrayList<>();
		for (GoodsSkuDO sku : list) {
			GoodsSkuVO skuVo = new GoodsSkuVO();
			BeanUtils.copyProperties(sku,skuVo);
			result.add(skuVo);
		}
		return result;
	}

	@Override
	public GoodsSkuVO getSkuFromCache(Integer skuId) {
		// 从缓存读取sku信息
		GoodsSkuVO skuVo = (GoodsSkuVO) cache.get(CachePrefix.SKU.getPrefix() + skuId);
		// 缓存中没有找到商品，或者最后修改时间为空（表示数据异常），从数据库中查询
		if (skuVo == null || skuVo.getLastModify()==null) {
			GoodsSkuDO sku = this.getModel(skuId);
			if (sku == null) {
				return null;
			}
			skuVo = new GoodsSkuVO();
			BeanUtils.copyProperties(sku,skuVo);

			//以下信息由商品中获取
			GoodsDO goods = this.daoSupport.queryForObject(GoodsDO.class, sku.getGoodsId());

			skuVo.setLastModify(goods.getLastModify());
			skuVo.setGoodsTransfeeCharge(goods.getGoodsTransfeeCharge());
			skuVo.setDisabled(goods.getDisabled());
			skuVo.setMarketEnable(goods.getMarketEnable());
			skuVo.setTemplateId(goods.getTemplateId());
			skuVo.setGoodsType(goods.getGoodsType());
			cache.put(CachePrefix.SKU.getPrefix() + skuId, skuVo);
			return skuVo;
		}
		return skuVo;
	}

	@Override
	public List<GoodsSkuDO> querySellerAllSku() {
		Seller seller = UserContext.getSeller();
		String sql = "select * from es_goods_sku s inner join es_goods g on s.goods_id = g.goods_id " +
				"where s.seller_id = ? and g.market_enable = 1 and g.disabled = 1 and g.is_auth = 1";
		return this.daoSupport.queryForList(sql,GoodsSkuDO.class,seller.getSellerId());
	}

	@Override
	public void checkSellerGoodsCount(Integer[] skuIds) {
		Seller seller = UserContext.getSeller();
		List<Object> term = new ArrayList<>();
		String idStr = SqlUtil.getInSql(skuIds, term);

		String sql = "select count(1) from es_goods_sku where sku_id in (" + idStr + ") and seller_id = ?";
		term.add(seller.getSellerId());
		Integer count = this.daoSupport.queryForInt(sql, term.toArray());
		if (count != skuIds.length) {
			throw new ServiceException(GoodsErrorCode.E301.code(), "存在不属于您的商品，不能操作");
		}
	}
}
